package archer.framework.web.entity;

import archer.framework.utils.RequestParamUtils;
import archer.framework.utils.ServletUtils;
import archer.framework.utils.SmartString;
import archer.framework.utils.UUIDUtils;
import jodd.json.meta.JSON;

import javax.servlet.ServletRequest;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;

import static archer.framework.utils.ValidateUtils.isNotEmpty;

/**
 * @author christ
 * @date 2015/11/17
 */
public class AccessLog {

    /**
     * log 名称
     */
    private String name;

    /**
     * http method
     */
    private String method;

    /**
     * 调用的url
     */
    private String url;

    /**
     * 调用者ip
     */
    private String ip;

    /**
     * 调用参数
     */
    private String params;

    /**
     * 用户代理
     */
    private String userAgent;

    /**
     * 访问时间点
     */
    private Timestamp accessDate;

    /**
     * 当前登录用户
     */
    private Object userId;

    /**
     * uuid
     */
    private String uuid = UUIDUtils.randomUUID();

    /**
     * 其他属性
     */
    private Map attrs = new HashMap();

    public AccessLog() {

    }

    public AccessLog(String name, ServletRequest request) {
        this.setName(name);
        this.setUrl(ServletUtils.getRequestURI(request));
        this.setParams(RequestParamUtils.getQueryStringWithMask(request.getParameterMap(), "password"));
        this.setMethod(ServletUtils.getMethod(request));
        this.setUserAgent(ServletUtils.getRequest(request).getHeader("User-Agent"));
        this.setAccessDate(new Timestamp(System.currentTimeMillis()));
        this.setIp(ServletUtils.getClientIp(request));
    }

    public String getName() {
        return name;
    }

    public AccessLog setName(String name) {
        this.name = name;
        return this;
    }

    public String getMethod() {
        return method;
    }

    public AccessLog setMethod(String method) {
        this.method = method;
        return this;
    }

    public String getUrl() {
        return url;
    }

    public AccessLog setUrl(String url) {
        this.url = url;
        return this;
    }

    public String getIp() {
        return ip;
    }

    public AccessLog setIp(String ip) {
        this.ip = ip;
        return this;
    }

    public String getParams() {
        return params;
    }

    public AccessLog setParams(String params) {
        this.params = params;
        return this;
    }

    public String getUserAgent() {
        return userAgent;
    }

    public AccessLog setUserAgent(String userAgent) {
        this.userAgent = userAgent;
        return this;
    }

    public Timestamp getAccessDate() {
        return accessDate;
    }

    public AccessLog setAccessDate(Timestamp accessDate) {
        this.accessDate = accessDate;
        return this;
    }

    public Map getAttrs() {
        return attrs;
    }

    public AccessLog setAttrs(Map attrs) {
        this.attrs = attrs;
        return this;
    }

    public Object getUserId() {
        return userId;
    }

    public AccessLog setUserId(Object userId) {
        this.userId = userId;
        return this;
    }

    public AccessLog addAttr(String key, Object value) {
        this.attrs.put(key, value);
        return this;
    }

    public String getUuid() {
        return uuid;
    }

    public AccessLog setUuid(String uuid) {
        this.uuid = uuid;
        return this;
    }

    @JSON(include = false)
    public String toLogStr() {

        StringBuilder sb = new StringBuilder();
        sb.append("\n\n=================[${name}]=================\n");
        sb.append("uuid : ${uuid}\n");
        sb.append("url : ${url}\n");
        sb.append("method : ${method}\n");
        sb.append("ip : ${ip}\n");
        sb.append("params : ${params}\n");
        sb.append("userId : ${userId}\n");
        sb.append("userAgent : ${userAgent}\n");
        sb.append("accessDate : ${accessDate}\n");

        if (isNotEmpty(attrs)) {
            for (Object each : attrs.keySet()) {
                sb.append(each).append(" : ${attrs.").append(each).append("}\n");
            }
        }
        sb.append("=================[${name}]=================\n\n");
        return SmartString.template(sb.toString()).bind(this).toString();
    }
}
